let a : object;
a = {}

// {} 用来指定对象中可以包含哪些属性
// 语法： {属性名：属性值,属性名：属性值}  在属性名后加?，表示属性可选
let b :{name:string,age?:number}
b = {name:'孙悟空'}


// -------------定义对象的结构-------------------------
// [propName:string]:unknown 表示任意类型的属性 
let c : {name:string,[propName:string]:any}
c = {name:'猪八戒',age:18,gender:'男'}

// --------------定义函数的结构--------------------------------
/**
 * 设置函数结构的类型声明
 *      语法：(形参：类型,形参：类型 ...) => 返回值类型
 */
let d: (a: number,b: number)=> number;
// d = function(n1,n2):number{
    // return 10;
// }

/**
 *      数组的类型声明：
 *              类型[]
 *              Array<类型>
 * 
 */
// string[] 表示字符串数组
let e1: string[];
e1 = ['a','b','c']

// number[] 表式数值数组
let f : number[];
f = [1,2,3] 

// Array<number>表示数值数组
let g: Array<number>
g = [1,2,3]

/**
 * 元组：就是固定长度的数组
 *    语法：[类型，类型，类型]
*/
let h:[string,number]
h = ['hello',123]

/**
 * enum 枚举
 * 
 */


// -------------------接口------------------------------
interface IPerson{
    firstName: string,
    lastName: string,
    sayHi:()=>string
}

var customer:IPerson = {
    firstName:'Tom',
    lastName: 'Hanks',
    sayHi :():string => {return 'Hi there'}
}
console.log('Customer 对象');
console.log(customer.firstName); //Tom
console.log(customer.lastName); //Hanks
console.log(customer.sayHi); // [Function: sayHi]

var employee = {
    firstName: 'Jim',
    lastName: 'Blakes',
    sayHi: function() {
        return 'Hello!'
    }
}
console.log('Employee 对象！');
console.log(employee.firstName);
console.log(employee.lastName);
console.log(employee.sayHi);

// ---------------------------联合类型和接口--------------------
interface RunOptions {
    program:string,
    commandline :string[] | string | (()=> string);
}

// commandline 是字符串
var options:RunOptions={
    program:'test1',commandline:'Hello'
}
console.log(options.commandline);

// commandline 是字符串数组
options = {
    program:'test2',
    commandline:['Hello','World'],
}
console.log(options.commandline[0]);
console.log(options.commandline[1]);
// commandline 是一个函数表达式
options = {
    program:'test3',
    commandline:()=>{return '** Hello World';}
}
var fn:any = options.commandline;
console.log(fn());

// 接口和数组  接口中我们可以将数组的索引值和元素设置为不同类型，索引值可以是数字或字符串
interface namelist{
    [index:number]:string
} 
// 类型一致，正确
var list2:namelist = ['Google','Runoob','TaoBao']
//  错误元素 1 不是string 类型
// var list2: namelist = ['Runoob',1,'Taobao']

interface ages {
    [index:string]:number
}

var agelist:ages;
agelist['runoob'] = 15
// agelist[2] = 'google'

//--------------- 接口继承---------------------
// ts允许接口继承多个接口

// 单继承实例
interface  Person1 {
    age: number
}
interface Musician extends Person1 {
    instrument: string
}
var drummer = <Musician>{};
drummer.age = 27;
drummer.instrument = 'Drums'
console.log('年龄：',drummer.age);
console.log('喜欢的乐器',drummer.instrument);

// 多继承实例
interface IParent1{
    v1: number
}
interface IParent2{
    v2: number
}
interface Child extends IParent1,IParent2{
}
var Iobj:Child = {v1:12,v2:23}
console.log('value 1:'+ Iobj.v1 + "value 2:" + Iobj.v2);

// ----------------类----------------------
/**
 * class class_name{
 *  // 类作用域
 * }
 */  
class Car { 
    // 字段
    engine:string
    // 构造函数
    constructor (engine:string){
        this.engine = engine
    }
    // 方法
    disp():void{
        console.log("发动机为："+ this.engine);
    }
}

// 创建实例化对象
/**
 * 语法如下：
 *   var object_name = new class_name([ arguments])
 */
// 创建一个Car类，然后通过new来创建一个对象并访问属性和方法

class Car1 {
    engine:string;
    constructor(engine:string){
        this.engine = engine
    }
    disp():void {
        console.log('函数中显示发动机型号：'+ this.engine);
    }
}
var obj = new Car1('XXSY1');
console.log(obj.engine);
obj.disp();

//-------------------------类的继承---------------------------------
/**
 * 语法；
 *   class child_class_name extends parent_class_name 
 */
class Shape {
    Area: number
    constructor(a: number){
        this.Area = a
    }
}
class Circle extends Shape{
    disp():void{
        console.log('圆的面积:',this.Area);
    }
}
var obj1 = new Circle(233)
obj1.disp()

// 注意：子类只能继承一个父类，ts不支持继承多个类，但支持多重继承
class Root{
    str: string
}
class Child extends Root{}
class Leaf extends Child{}  // 多重继承，继承了Child 和 Root类

var obj2 = new Leaf()
obj2.str = 'hello'
console.log(obj2.str);

// 继承类的方法重写
class PrinterClass {
    doPrint():void {
        console.log('父类的doPrint() 方法');
    }
}
class StringPrinter extends PrinterClass{
    doPrint(): void {
        super.doPrint() // 调用父类的构造函数
        console.log('子类的doPrint()方法');
    }
}
// static 用于定义类的数据成员（属性和方法）为静态的，可以直接通过类名调用静态成员
// instanceof 运算符用于判断对象是否指向指定的类型，返回值是boolean类型
var p1 = new PrinterClass()
var isPrinterClass = p1 instanceof PrinterClass;
console.log("p1对象是PrinterClass 类实例化而来的"+ isPrinterClass); // true

// 命名空间
namespace SomeNameSpaceName{
    export interface ISomeInterfaceName{draw();}
    export class SomeClassName{}
}
// 调用
SomeNameSpaceName.SomeClassName;

